import _thread
import json
from os import path
from typing import List
from uuid import uuid4

from fitz import fitz
from flask import Blueprint, request

from apps.db import db
from apps.logger_config import logger
from apps.model import BankSideInfo, BorrowerInfo, BankSideExtendInfo, File, HouseApprove, HouseConfirm, DiyaPerson, \
    Counter
from apps.seleuinms.process import YzyhThread, Job
from apps.seleuinms.process.house import HouseThread
from apps.seleuinms.requests.HouseRequest import HouseRequest
from apps.seleuinms.requests.YzyhRequest import YzyhRequest, get_package_info
from apps.utils import Response, model_dict_clear, obj_underline2hump, getRequestData, print_file, camel_to_line, \
    camel_json_to_line
from apps.utils.docx_utils import generate_table

robot = Blueprint('robot', __name__)

exec_path = path.join(path.curdir, '../exec')
thread_map = {}


def find_diff(seg1: List[str], seg2: List[str]):
    add = []
    remove = []
    update = []
    for seg in seg1:
        if seg not in seg2:
            add.append(seg)
        else:
            update.append(seg)
    for seg in seg2:
        if seg not in seg1:
            remove.append(seg)
        elif seg not in update:
            update.append(seg)
    return add, remove, update


def person_need_update(data1: dict, data2: DiyaPerson):
    return not (data1.get('name') == data2.name and data1.get('telphone') == data2.telphone and data1.get(
        'certNo') == data2.cert_no)


@robot.route("/start")
def start():
    if thread_map.get('yzyh') is None:
        # thread = YzyhThread(database=db)
        # thread.start()
        thread1 = HouseThread()
        thread1.start()
        thread_map['yzyh'] = [thread1]
    return Response.success({'done': True})


@robot.route("/state")
def state():
    if thread_map.get('yzyh') is None:
        return Response.success({'running': False})
    else:
        thread = thread_map.get('yzyh')
        for t in thread:
            if not t.is_alive():
                stop()
                return Response.success({'running': False})
        return Response.success({'running': True})


@robot.route("/stop")
def stop():
    if thread_map.get('yzyh') is not None:
        threads: List[Job] = thread_map.get('yzyh')
        for t in threads:
            t.stop()
        thread_map.pop('yzyh')
    return Response.success({'done': True})


@robot.route("/bank_detail", methods=['GET'])
def get_bank_detail():
    bank_id = dict(request.args).get('id')
    if bank_id is None:
        return Response.error('参数错误')
    info = BankSideInfo.get(bank_id)
    if info is None:
        return Response.error('未找到数据')
    info = model_dict_clear(info.__dict__)
    extend_data = BankSideExtendInfo.filter_by(contract_id=bank_id).all()
    extend_data = [model_dict_clear(d.__dict__) for d in extend_data]
    extend_ids = [e.get('id') for e in extend_data]
    borrowers = BorrowerInfo.filter(BorrowerInfo.extend_id.in_(extend_ids)).all()
    borrowers = [model_dict_clear(d.__dict__) for d in borrowers]
    diys = DiyaPerson.filter(DiyaPerson.extend_id.in_(extend_ids)).all()
    diys = [model_dict_clear(d.__dict__) for d in diys]
    data = {
        'diys': obj_underline2hump(diys),
        'borrowers': obj_underline2hump(borrowers),
        'extendData': obj_underline2hump(extend_data),
        'info': obj_underline2hump(info),
    }
    return Response.success(data)


@robot.route('/get_data_from_bank', methods=['POST'])
def get_data_from_bank():
    params = getRequestData()
    # if not params or (params.get('name') is None and params.get('certNo') is None):
    #     return Response.error('请输入抽取参数！')
    YzyhThread().executor(name=params.get('name'), cert_no=params.get('certNo'))
    return Response.success()


@robot.route('/get_approve_detail', methods=['POST'])
def get_approve_detail():
    aids = getRequestData().get('approveIdList')
    cids = getRequestData().get('confirmIdList')
    if not cids and not aids:
        return Response.error('参数错误')
    sql = """
    SELECT
        c.*,
        b.custom_name 
    FROM
        tb_house_confirm c
        LEFT JOIN tb_bank_side_extend e ON e.id = c.extend_id
        LEFT JOIN tb_bank_side_info b ON b.id = e.contract_id
    WHERE
        b.id IN ({ids})
    """.format(ids=",".join(["'{i}'".format(i=i) for i in cids]))
    confirms = db.session.execute(sql).fetchall()
    confirms = [dict(c) for c in confirms]

    sql = """
    SELECT
        c.*,
        b.custom_name 
    FROM
        tb_house_approve c
        LEFT JOIN tb_bank_side_extend e ON e.id = c.extend_id
        LEFT JOIN tb_bank_side_info b ON b.id = e.contract_id 
    WHERE
        b.id IN ({ids})
    """.format(ids=",".join(["'{i}'".format(i=i) for i in aids]))

    approves = db.session.execute(sql).fetchall()
    approves = [dict(c) for c in approves]

    approves += confirms
    return Response.success(approves)


def check_detail(commit_id):
    # 检查当前单据是否存在
    info = BankSideInfo.get(commit_id)
    if info is None:
        return Response.error("单据不存在")
    extend_infos = BankSideExtendInfo.filter_by(contract_id=commit_id).all()
    if extend_infos is None or len(extend_infos) == 0:
        return Response.error("单据不存在")
    for extend in extend_infos:
        borrowers = BorrowerInfo.filter_by(extend_id=extend.id).all()
        if borrowers is None or len(borrowers) == 0:
            return Response.error("借款人信息不存在")
        files = File.filter_by(history_id=extend.id).all()
        if files is None or len(files) == 0:
            return Response.error("关联文件不存在, 请上传")
    return Response.success()


@robot.route('/bank_commit_to_house', methods=['POST'])
def bank_commit_to_house():
    """填报不动产系统"""
    params = getRequestData()
    commitId = params.get('id')
    zl: dict = params.get('zl')
    borrowers = params.get('borrowers')
    diyas = params.get('diyaPersons')

    if commitId is None:
        return Response.error('参数错误')
    res = check_detail(commitId)
    if not json.loads(res).get('success'):
        return res
    # 填报房管局系统
    info = BankSideInfo.get(commitId)
    baseWork_flow_name = info.baseWork_flow_name

    # 根据传入参数修改当前单据相关信息，需要修改的是坐落，抵押人，借款人
    if zl:
        for key in zl:
            extend: BankSideExtendInfo = BankSideExtendInfo.get(key)
            extend.house_located = zl.get(key)
            extend.save()

    if borrowers:
        for key in borrowers:
            borrower_list = [camel_json_to_line(item) for item in borrowers.get(key)]
            db_borrowers = BorrowerInfo.filter_by(extend_id=key).all()
            b_ids = [b.get('id') for b in borrower_list]
            db_ids = [b.id for b in db_borrowers]

            add, remove, update = find_diff(b_ids, db_ids)
            for b in borrower_list:
                if b.get('id') in add:
                    BorrowerInfo(**b).save()
            for b in db_borrowers:
                if b.id in remove:
                    b.delete()
            for b_id in update:
                b = list(filter(lambda item: item.get('id') == b_id, borrower_list))[0]
                db_b = list(filter(lambda item: item.id == b_id, db_borrowers))[0]
                if person_need_update(b, db_b):
                    for d_key in b:
                        db_b.__setattr__(camel_to_line(d_key), b.get(d_key))
                    db_b.save()

    if diyas:
        for key in diyas:
            # 参数传递的抵押人信息列表
            diya_list = [camel_json_to_line(item) for item in diyas.get(key)]
            db_diyas: List[DiyaPerson] = DiyaPerson.filter_by(extend_id=key).all()
            d_ids = [d.get('id') for d in diya_list]
            db_ids = [d.id for d in db_diyas]

            add, remove, update = find_diff(d_ids, db_ids)
            for d in diya_list:
                if d.get('id') in add:
                    # 新增
                    DiyaPerson(**d).save()
            for d in db_diyas:
                if d.id in remove:
                    d.delete()
            for d_id in update:
                # 找到两个数据
                d = list(filter(lambda item: item.get('id') == d_id, diya_list))[0]
                db_d = list(filter(lambda item: item.id == d_id, db_diyas))[0]
                if person_need_update(d, db_d):
                    for d_key in d:
                        db_d.__setattr__(camel_to_line(d_key), d.get(d_key))
                    db_d.save()

    db.session.commit()

    if '个人一手' in baseWork_flow_name:
        # 设置状态为等待提交
        info = BankSideInfo.get(commitId)
        info.state = 'waitCompleteHouse'
        info.save()
        try:
            _thread.start_new(HouseRequest().process_first_house, (commitId,))
        except Exception as e:
            db.session.rollback()
            return Response.error(str(e))
    elif '个人二手' in baseWork_flow_name:
        """直接将当前单据修改为等待审核"""
        """当前状态已经为等待审核了"""
        pass
    else:
        # 设置状态为等待提交
        info = BankSideInfo.get(commitId)
        info.state = 'waitCompleteHouse'
        info.save()
        try:
            _thread.start_new(HouseRequest().process_second_house, (commitId,))
        except Exception as e:
            db.session.rollback()
            return Response.error(str(e))
    db.session.commit()
    return Response.success()


@robot.route('/house_commit_to_bank', methods=['POST'])
def house_commit_to_bank():
    """填报抵押等级证明"""
    aids = getRequestData().get('approveIdList')
    cids = getRequestData().get('confirmIdList')
    if aids is None and cids is None:
        return Response.error('参数错误')
    # 设置状态为等待提交
    for commitId in cids:
        info: BankSideInfo = BankSideInfo.get(commitId)
        info.state = 'waitCompleteBank'
        info.save()
    for commitId in aids:
        info: BankSideInfo = BankSideInfo.get(commitId)
        info.state = 'waitCompleteBank'
        info.save()
        # 填报代办中的数据
    try:
        _thread.start_new(YzyhRequest().process_house_datas, (aids, cids))
    except Exception as e:
        logger.error('填报银行系统报错： %s', str(e))
        db.session.rollback()
        return Response.error(str(e))
    db.session.commit()
    return Response.success()


approve_base_path = path.abspath(path.join(path.dirname(path.abspath(__file__)), '../../static/chanquan'))
table_file_path = path.abspath(path.join(path.dirname(path.abspath(__file__)), '../../'))


def pdf_addone(file, text, count):
    file_path = path.join(approve_base_path, file)
    if path.exists(file_path):
        # 为 pdf 加上水印
        doc = fitz.open(file_path)
        page = doc[0]
        page.cleanContents()
        p1 = fitz.Point(200, 700)
        p2 = fitz.Point(200, 750)
        page.insertText(p1, text, fontsize=24)
        page.insertText(p2, count, fontsize=24)
        page.setRotation(90)

        uuid = uuid4()
        doc.save("D:\\" + str(uuid) + '.pdf', garbage=4)

        # 打印
        print_file("D:\\" + str(uuid) + '.pdf')
        # 删除 文件
        # os.remove("D:\\" + str(uuid) + '.pdf')


def print_table(count_list, items):
    """
        {
            zw: '',
            diya: '',
            qzName: '抵押登记证明',
            amount: '1',
            qzNo: '',
        }
    """
    uuid = str(uuid4())
    file_path = path.join(table_file_path, uuid + '.docx')
    generate_table(count_list, items, file_path)
    print_file(file_path)


@robot.route('/print', methods=['POST'])
def print_pdf():
    contract_id = getRequestData().get('id')
    if not contract_id:
        return Response.error('参数错误')

    info: BankSideInfo = BankSideInfo.get(contract_id)
    if info.state != 'completed':
        return Response.error('当前单据状态不是完成，不能打印')
    business_key = info.business_key
    extend_list: List[BankSideExtendInfo] = BankSideExtendInfo.filter_by(contract_id=info.id).all()

    # 查询这个申请下所有的封包信息
    if not YzyhRequest.cookie_dict:
        YzyhRequest.login()
    res = get_package_info(business_key, YzyhRequest.cookie_dict)
    data = res.get('data')

    """
        :key: package_no
        :value: List[BankSideExtendInfo]
    """
    package_map = {}

    for extend in extend_list:
        for item in data:
            warrantInfoList = item.get('warrantInfoList')  # 押品信息
            for warrant in warrantInfoList:
                if warrant.get('collatId') == extend.collat_id and warrant.get('ownershipVchrTypeCode') == '40':
                    # 当前押品为这个包
                    if package_map.get(item.get('package_map')) is None:
                        package_map[item.get('packetNo')] = []
                    package_map[item.get('packetNo')].append(extend)
                    break

    if list(package_map.keys()) == 0:
        return Response.error('没有封包数据')

    # 总共需要封这么多包 key 为 package_no 封包号
    count_list = []
    items = []
    """
    {
        zw: '',
        diya: '',
        qzName: '抵押登记证明',
        amount: '1',
        qzNo: '',
    }
    """
    # rwLock: RWLock = g.rw_lock
    for key in package_map:
        # key 封包号
        # 根据权证匹配封包号

        extends: List[BankSideExtendInfo] = package_map.get(key)
        for extend in extends:
            # 所有的权证信息 approve_list
            # 当前申请是一手房还是其他的
            if '个人一手' in info.baseWork_flow_name:
                # 个人一手业务，需要获取正式抵押登记证明
                approve = HouseConfirm.filter_by(extend_id=extend.id).first()
            else:
                approve = HouseApprove.filter_by(extend_id=extend.id).first()

            # if approve.count is None:
            #     # count 封包编号
            #     approve.count = Counter.get_count()
            #     approve.save()
            count = Counter.get_count()
            count_list.append(count)

            borrowers = BorrowerInfo.filter_by(extend_id=extend.id).all()
            diyas = DiyaPerson.filter_by(extend_id=extend.id).all()

            # 打印权证pdf
            pdf_addone(approve.file, key, count)
            item = {
                'zw': ','.join([d.name for d in borrowers]),
                'diya': ','.join([d.name for d in diyas]),
                'qzName': '抵押登记证明',
                'amount': '1',
                'qzNo': approve.qz_no,
                'remark': '/'
            }
            items.append(item)
    # 打印列表
    print_table(count_list, items)
    db.session.commit()
    return Response.success()
